%{
    #include "Scanner.h"
    using namespace LALG;
    
    typedef LALG::Parser::token token;
%}

%option yylineno yyclass="Scanner" noyywrap c++

C    [ -~]
C2   [ -~]{-}['\\]
C3   [ -~]{-}["\\]
BL   \\
L    [a-zA-Z_]
D    [0-9]
WS   [ \r\t]
NSL  [!-~]{-}[:<>;.=:,+\-*/()]
NSN  [!-~]{-}[:<>;=:,+\-*/()]

%%

    /*-----------------------------------------------------------------------------
     *  Regras para eliminação de comentários e comentário não fechado
     *-----------------------------------------------------------------------------*/
"{"[^}]*"}" {  }

"{"[^}]*    { 
    printError(LEX_BCNC); 
    yyterminate(); 
}

    /*-----------------------------------------------------------------------------
     *  Regras de eliminação de espaços em brancos
     *-----------------------------------------------------------------------------*/
{WS}+   {  }

[\n]+   {  }


    /*-----------------------------------------------------------------------------
     *  Regra para produção de identificadores muito grandes
     *-----------------------------------------------------------------------------*/
{L}({L}|{D}){20,} {
    printError(LEX_LONG_ID);
    return token::T_LONG_ID;
}

    /*-----------------------------------------------------------------------------
     *  Regra para produção de identificadores
     *-----------------------------------------------------------------------------*/
{L}({L}|{D})* {
    yylval->sval = new string(yytext);
    return checkID(); 
}

    /*-----------------------------------------------------------------------------
     *  Regras para produções de números inteiros e reais
     *-----------------------------------------------------------------------------*/
{D}+    {
    yylval->ival = atoi(yytext);
    return token::T_NINTEGER; 
}

({D}*"."{D}+)|({D}+"."{D}*)     {
    yylval->fval = atof(yytext);
    return token::T_NREAL; 
}

    /*-----------------------------------------------------------------------------
     *  Regras para número real mal formado: 1a1b.1, 1.a1 ou 1a.a1
     *-----------------------------------------------------------------------------*/
{D}{NSN}*"."{NSN}*      { 
    printError(LEX_MF_REAL); 
    return token::T_MF_REAL; 
}

    /*-----------------------------------------------------------------------------
     *  Regra para número inteiro mal formado: 123a ou 123@ ou 123ab123
     *-----------------------------------------------------------------------------*/
{D}{NSN}*   { 
    printError(LEX_MF_INTEGER); 
    return token::T_MF_INTEGER; 
}

    /*-----------------------------------------------------------------------------
     *  Regra para identificador mal formado: asds$ds abc@
     *-----------------------------------------------------------------------------*/
{L}{NSL}*   { 
    printError(LEX_MF_ID); 
    return token::T_MF_ID; 
}

    /*-----------------------------------------------------------------------------
     *  Regras para produção de símbolos reservados
     *-----------------------------------------------------------------------------*/
":="    { return token::T_ASSIGN; }
"<>"    { return token::T_DIFF; }
">="    { return token::T_GRTR_EQ; }
"<="    { return token::T_LSSR_EQ; }
";"     { return token::T_SEMICOLON; }
"."     { return token::T_DOT; }
"="     { return token::T_EQUAL; }
":"     { return token::T_COLON; }
","     { return token::T_COMMA; }
">"     { return token::T_GREATER; }
"<"     { return token::T_LESSER; }
"+"     { return token::T_PLUS; }
"-"     { return token::T_MINUS; }
"*"     { return token::T_TIMES; }
"/"     { return token::T_DIVISION; }
"("     { return token::T_LEFT_PAREN; }
")"     { return token::T_RIGHT_PAREN; }

    /*-----------------------------------------------------------------------------
     *  Regras para erros de símbolos desconhecidos
     *-----------------------------------------------------------------------------*/
.       { 
    printError(LEX_UNKNOWN);
    return token::T_UNKNOWN; 
}

